//
// Created by liu on 1/16/21.
//
#ifndef SOCKETFDCLIENTMANAGE_H
#define SOCKETFDCLIENTMANAGE_H

#include <string>
#include <vector>

//Server and client protocol process type.
typedef enum
{
    SERVER_CLIENT_TOPIC_TYPE,
    SERVER_CLIENT_SERVICE_TYPE,
    SERVER_CLIENT_TYPE_COUNT
}ServerClientPPType;

//Client block type.
typedef enum
{
    BLOCK_CLIENT_ENUM,
    NOBLOCK_CLIENT_ENUM
}ClientBlockType;

//Broadcast type.
typedef enum
{
    BROADCAST_SERVER_ENUM,
    NOBROADCAST_SERVER_ENUM
}BroadcastEnumType;

typedef bool (*PPFunctionPointer)(int serviceClientFD, int &errCode);

//Client manage type.
typedef struct{
    int clientName;                      //Client name
    int clientFD;                        //Client FD assigned from socket
    BroadcastEnumType broadcast;         //Broadcast from server
    ServerClientPPType clientPPType;     //Protocol process type
    PPFunctionPointer pPFunctionPointer; //Function pointer to process feedback(for protocol process type)
}ClientManageType;


//Socket FD client manage class.
class SocketClientFDManage {
public:
    std::string printErr{"SocketClientFDManage Error: "};
    std::string printPre{"SocketClientFDClientManage: "};

    //Constructor
    SocketClientFDManage();

    //
    //Client management.
    //
    //Add client for managing.
    bool clientManageAdd(ClientManageType newClient);

    //Erase client FD.
    bool clientFDErase(int ClientFD);

    //Get all client FDs.
    bool clientFDGet(std::vector<int> &clientFDs);

    //Get client FDs with given ServerClientPPType.
    bool clientFDGet(ServerClientPPType clientPPType, std::vector<int> &clientFDs);

    //Get client FDs with given BroadcastEnumType.
    bool clientFDGet(BroadcastEnumType broadcast, std::vector<int> &clientFDs);

    //Get client protocol process function pointer with given clientFD.
    PPFunctionPointer clientPPPointerGet(int clientFD);

    //Print all clients.
    void clientPrintAll();


    //
    //Utile functions.
    //
    //Find max FD.
    int findMaxFD();

    //Check uniqueness of client name.
    bool uniqueOfClientName(int clientName);

public:
    //Convert from ServerClientPPType to string.
    std::string convertFromServerClientPPTypeToString(ServerClientPPType ppType);


    //
    //Private variables.
    //
private:
    //Client manages. Including protocol process type, FDs and MessageProcessProperty function pointer.
    std::vector<ClientManageType> clientManages;

};


#endif // SOCKETFDCLIENTMANAGE_H
